﻿using System;
using System.Linq.Expressions;
using System.Web.Mvc;

namespace MvcPatch
{
    [Reusable]
    [AttributeUsage(ValidTargets, AllowMultiple = false, Inherited = false)]
    public class BinderAttribute : CustomModelBinderAttribute
    {
        internal const AttributeTargets ValidTargets = AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Struct;

        public BinderAttribute(Type binderType)
            : this(binderType, true)
        {
        }

        public BinderAttribute(Type binderType, bool singleton)
        {
            if (binderType == null)
            {
                throw new ArgumentNullException("binderType");
            }

            if (!typeof(IModelBinder).IsAssignableFrom(binderType))
            {
                var message = String.Format("{0} doesn't implement IModelBinder.", binderType.FullName);
                throw new ArgumentException(message, "binderType");
            }

            this.BinderType = binderType;

            if (singleton)
            {
                var instance = (IModelBinder)Activator.CreateInstance(binderType);
                this.m_binderGetter = () => instance;
            }
            else
            {
                this.m_binderGetter = () => (IModelBinder)Activator.CreateInstance(binderType);
            }
        }

        public Type BinderType { get; private set; }

        private readonly Func<IModelBinder> m_binderGetter;

        public override IModelBinder GetBinder()
        {
            return this.m_binderGetter();
        }
    }
}
